Introduccion

En Argentina, el “dólar blue” hace referencia a la cotización no oficial del dólar estadounidense en el mercado paralelo. A diferencia del tipo de cambio oficial establecido por el Banco Central de la República Argentina (BCRA), el dólar blue es un valor determinado por la oferta y la demanda en un mercado no regulado. Esta cotización suele ser utilizada como un indicador de la percepción del mercado sobre la estabilidad económica y financiera del país. Las variaciones en el valor del dólar blue pueden tener un impacto significativo en la economía argentina, ya que influyen en la inflación, los precios, la inversión y la forma de ahorro de las personas.

Objetivo

El propósito central de este programa es crear un modelo para predecir el comportamiento del dólar blue en Argentina. Para alcanzar este objetivo, se utilizarán las variables del REM (Relevamiento de Expectativas de Mercado) y asi podremos usar dichas predicciones para pronosticar el valor del dolar a seis meses futuros. Este relevamiento junta proyecciones realizadas de diversos analistas económicos y financieros del país.

Predicciones del REM:

El Relevamiento de Expectativas de Mercado (REM) constituye una herramienta fundamental del Banco Central de la República Argentina. Su finalidad es recopilar las proyecciones de especialistas del mercado en relación con variadas variables económicas clave. Estas variables son:

  1. Crecimiento del Producto Interno Bruto (PIB): Representa la expansión económica del país en un período específico.
  2. Inflación o Indice de Precios al Consumidor (IPC): Refleja el aumento generalizado y sostenido de los precios en la economía.
  3. Tasa de Interés (BADLAR): Indica el costo del dinero y puede influir en la inversión y el ahorro.
  4. Tipo de Cambio: Es el valor de la moneda nacional en relación con otras monedas, como el dólar estadounidense.
  5. Balanza Comercial: Muestra la diferencia entre las exportaciones e importaciones de bienes.
  6. Desocupacion porcentual: Muestra el porcentaje de la poblacion economicamente activa que se encuantra desempleada.

Disclaimer

Es fundamental remarcar que el mercado del dólar blue en Argentina es altamente volátil y está sujeto a influencias complejas y variables sociales imposibles de predecir. Por lo tanto, cualquier pronóstico generado a través de este programa debe ser considerado como una APROXIMACIÓN y una herramienta orientativa, NO como una predicción infalible. Los resultados obtenidos deben ser interpretados con precaución y no deben constituir la única base para la toma de decisiones financieras importantes. Ademas por la naturaleza de los datos seria oportuno realizar un analisi de series de tiempo o datos longitudinales, pero ese no es el objetivo de este informe.

Data

Los datos fueron tomados de fuentes confiables como Ambito Financiero o series historicas publicadas por el INDEC o la secretaria de datos del gobierno.

Como se muestra, tomamos solo datos desde el mes de diciembre de 2016, algunas series son mensuales, otras trimestrales y otras diarias, para facilitar el ajuste del modelo decidí mensualizar los datos con una intrapolacion spline en el caso de los datos trimestrales (como lo son PBI y desocupacion porcentual) y tomar la primer observacion de cada mes en el caso de las series diarias (como lo son tasa de interes y tipo de cambio)

Modelo Lineal

Ajustamos un modelo lineal y vemos en la tabla ANOVA que solamente el dolar oficial, la tasa de interes y las importaciones son significativas, junto al PBI si usamos un nivel de significacion del 10%. Para aplicar este modelo estoy suponiendo que los datos son independientes igualmente distribuidos y que los residuos se distribuyen de forma normal con variancia constante (supuestos que sabemos que no son reales). Continuo el analisis con la comprobacion de dichos supuestos.

Residuos

# Calcular los residuos estandarizados
residuos <- residuals(model)
fitted_values <- model$fitted.values

# Crear un data frame con los residuos estandarizados y los valores ajustados
residuals_df <- data.frame(Fitted_Values = fitted_values, Residuales = residuos)

# Graficar los residuos estandarizados versus los valores ajustados
g1=ggplot(residuals_df, aes(x = Fitted_Values, y = Residuales)) +
  geom_point(shape = 20) +
  geom_hline(yintercept = 0, color = "red") +
  xlab("Valores Ajustados") +
  ylab("Residuos Estandarizados") +
  ggtitle("Gráfico de Residuos Estandarizados vs. Valores Ajustados")
# Gráfico QQ de los residuos estandarizados
g2=ggplot(data.frame(Residuales = residuos), aes(sample = Residuales)) +
  geom_qq() +
  geom_qq_line() +
  xlab("Cuantiles Teóricos") +
  ylab("Cuantiles de los Residuos Estandarizados") +
  ggtitle("Gráfico QQ de los Residuos Estandarizados")
plot_grid(g1,g2)

Realizamos los graficos de residuos estandarizado vs valores ajustados y vemos que a medida que aumenta el valor ajustado tambien aumenta la variancia de los residuos y que los cuantiles observados podrian asimejarse a una distribucion normal, de igual forma nos valdremos de tests estadisticos para terminar de concluir.

shapiro.test(residuos)
## 
##  Shapiro-Wilk normality test
## 
## data:  residuos
## W = 0.97896, p-value = 0.2171

El Shapiro Test plantea: $ H_0) $ Los datos provienen de una población que sigue una distribución normal. $ H_1) $ Los datos no provienen de una población que sigue una distribución normal. Y como el valor de probabilidad asociado es mayor a 0.05 podemos asumir que se cumple la hipotesis nula.

bptest(model) 
## 
##  studentized Breusch-Pagan test
## 
## data:  model
## BP = 21.773, df = 7, p-value = 0.002779

El test de Breusch-Pagan plantea: $ H_0) $ La varianza de los residuos es constante (homocedasticidad). $ H_1) $ La varianza de los residuos no es constante (heterocedasticidad). Y como el valor de probabilidad asociado es menor a 0.05 podemos asumir que se cumple la hipotesis nula.

Nuevamente vale aclarar que estos test usan supuestos de normalidad, los cuales sabemos que no son reales, por lo que deberiamos usar algun tipo de test no parametrico, pero a fines prácticos al usuario no le interesa el cumplimiento de estos supuestos sino que tan bien ajusta el modelo.

Transformacion

Visto y considerando el incumplimiento de los supuesto y que, en los ultimos años, el crecimiento tanto del dolar como de la tasa de interes no fue lineal sino mas bien cuadratico o exponencial, decidi aplicar transformaciones al modelo lineal. Luego de muchas pruebas practicas observe que las predicciones mas exactas y estables se daban aplicando transformacion logaritmica a todas las variables.

Podriamos repetir la interpretación arriba mencionada con la diferencia de que ahora exportación y desocupación mensual son las únicas no significativas (de igual forma no las eliminaremos del modelo)

Residuos Log

# Calcular los residuos estandarizados
residuos_log <- residuals(modelog)
fitted_values_log <- modelog$fitted.values

# Crear un data frame con los residuos estandarizados y los valores ajustados
residuals_df <- data.frame(Fitted_Values = fitted_values_log, Residuales = residuos_log)

# Graficar los residuos estandarizados versus los valores ajustados
g1=ggplot(residuals_df, aes(x = Fitted_Values, y = Residuales)) +
  geom_point(shape = 20) +
  geom_hline(yintercept = 0, color = "red") +
  xlab("Valores Ajustados") +
  ylab("Residuos Estandarizados") +
  ggtitle("Gráfico de Residuos Estandarizados vs. Valores Ajustados")
# Gráfico QQ de los residuos estandarizados
g2=ggplot(data.frame(Residuales = residuos_log), aes(sample = Residuales)) +
  geom_qq() +
  geom_qq_line() +
  xlab("Cuantiles Teóricos") +
  ylab("Cuantiles de los Residuos Estandarizados") +
  ggtitle("Gráfico QQ de los Residuos Estandarizados")
plot_grid(g1,g2)

bptest(modelog) 
## 
##  studentized Breusch-Pagan test
## 
## data:  modelog
## BP = 10.813, df = 7, p-value = 0.147
shapiro.test(residuos_log)
## 
##  Shapiro-Wilk normality test
## 
## data:  residuos_log
## W = 0.9839, p-value = 0.4223

A diferencia del análisis anterior, aqui si vemos un cumplimiento de los supuestos tanto graficamente como en los test aplicados.

Interpretacion

El modelo al que le introduciremos las predicciones del REM para obtener valores de dolar blue futuro será entonces:

\[ log(DolarBlue)=17.5+1.13*log(Dolar Oficial)-0.32*log(Tasa Interes)+0.3*log(IPC_{100})-1.55*log(PBI)+0.31*log(Importacion) \]

  1. log_doficial
  2. log_tasa_interes
  3. log_ipc_nacional (base 100 en diciembre de 2016)
  4. log_pib_mensual (en millones de dolares)
  5. log_importacion (en millones de dolares)
  6. log_desocupacion_porc
  7. lo_exportacion (en millones de dolares)

Aplicación gráfica

Para visualizar como predice el modelo que ajustamos tomaremos las predicciones de los datos que ya tenemos y las compararemos con los valores reales que tuvo el dolar blue. Ademas le agegamos dos bandas al grafico, una que indica el 170% y otra que indica el 210% del valor del dolar oficial que por evidencia observacional son las franjas entre las que estuvo fluctuando el dolar blue en los ultimos años.

Base_2016a23$ypredlog=exp(predict(modelog,newdata = Base_2016a23))
Base_2016a23$doficial17=Base_2016a23$doficial*1.7
Base_2016a23$doficial21=Base_2016a23$doficial*2.1
grafico_plotly <- plot_ly(data = Base_2016a23, x = ~fecha) %>%
  add_lines(y = ~venta, name = "Venta", line = list(color = "blue")) %>%
  add_lines(y = ~ypredlog, name = "Predicciones", line = list(color = "red")) %>%
  add_lines(y = ~doficial17, name = "170% Dolar Oficial", line = list(color = "gray", dash = "dash")) %>%
  add_lines(y = ~doficial21, name = "210% Dolar Oficial", line = list(color = "gray", dash = "dash")) %>%
  layout(title = "Comparación Predicciones vs Blue real",
         xaxis = list(title = "Fecha"),
         yaxis = list(title = "Valores"))

grafico_plotly

Conclusion

Aplicando las predicciones que se publican en el REM y utilizando este modelo podemo tener una nocion del comportamiento futuro del dolar blue. En la practica podemos ir actualizando los datos que ajustan la modelo y observando los resultados. En mi experiencia, si bien el modelo sobre estima, resulta util para identificar un salto cercano como se dio por ejemplo luego de las elecciones PASO 2023

Adicional: Otros Modelos Ajustado

Como remarque durante todo el informe, sabemos que el dolar blue no se comporta de forma lineal y que estos modelos estan ajustados a base de supuestos erroneos. Por esto podria continuarse el analisis ajustando un modelo aditivo no lineal.

modelo_blue_aditivo=gam(venta ~ s(doficial) + s(exportacion) + s(importacion) + s(tasa_interes) + s(pib_mensual) + s(desocupacion_porc) + s(ipc_nacional),
                        data = Base_2016a23)
summary(modelo_blue_aditivo)
## 
## Family: gaussian 
## Link function: identity 
## 
## Formula:
## venta ~ s(doficial) + s(exportacion) + s(importacion) + s(tasa_interes) + 
##     s(pib_mensual) + s(desocupacion_porc) + s(ipc_nacional)
## 
## Parametric coefficients:
##             Estimate Std. Error t value Pr(>|t|)    
## (Intercept) 126.5706     0.3645   347.3   <2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Approximate significance of smooth terms:
##                        edf Ref.df      F  p-value    
## s(doficial)          7.806  8.397 16.257  < 2e-16 ***
## s(exportacion)       1.000  1.000 17.548 0.000155 ***
## s(importacion)       4.117  5.077  3.079 0.021478 *  
## s(tasa_interes)      7.217  7.860  4.102 0.002274 ** 
## s(pib_mensual)       5.364  6.246  0.612 0.693465    
## s(desocupacion_porc) 5.003  5.880  4.305 0.004170 ** 
## s(ipc_nacional)      8.390  8.703 18.721  < 2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## R-sq.(adj) =  0.999   Deviance explained =  100%
## GCV = 21.203  Scale est. = 10.495    n = 79

No profundarisare en el analisis de este modelo por falta de erramientas teoricas, pero podriamos observarlo y compararlo en el grafico anterior

Base_2016a23$ypredgam=predict(modelo_blue_aditivo,newdata = Base_2016a23)
grafico_plotly <- plot_ly(data = Base_2016a23, x = ~fecha) %>%
  add_lines(y = ~venta, name = "Venta", line = list(color = "blue")) %>%
  add_lines(y = ~ypredlog, name = "Modelo Log", line = list(color = "red")) %>%
  add_lines(y = ~ypredgam, name = "Modelo GAM", line = list(color = "green")) %>%
  add_lines(y = ~doficial17, name = "170% Dolar Oficial", line = list(color = "gray", dash = "dash")) %>%
  add_lines(y = ~doficial21, name = "210% Dolar Oficial", line = list(color = "gray", dash = "dash")) %>%
  layout(title = "Comparación Predicciones vs Blue real",
         xaxis = list(title = "Fecha"),
         yaxis = list(title = "Valores"))

grafico_plotly

Las predicciones de este modelo practimaente se superponen con el valor real que fue tomando el dolar blue, lo que indica un gran ajuste, pero en la practica un pequeño cambio en las exportaciones aumentaba mucho el error, lo que nos lleva a usarlo solo como un complemento del modelo anterior.

LS0tDQp0aXRsZTogIk1vZGVsYWNpb24gZGUgZG9sYXIgYmx1ZSBBcmdlbnRpbmEiDQphdXRob3I6ICJSb21hbiBMYW5kYSINCmRhdGU6ICIyMDIzLTA4LTA1Ig0Kb3V0cHV0Og0KICBodG1sX2RvY3VtZW50Og0KICAgIHRvYzogVFJVRQ0KICAgIHRvY19mbG9hdDogVFJVRQ0KICAgIGNvZGVfZG93bmxvYWQ6IFRSVUUNCiAgICB0aGVtZTogdW5pdGVkDQogICAgZGZfcHJpbnQ6IHBhZ2VkDQpsaW5rLWNpdGF0aW9uczogeWVzDQotLS0NCg0KYGBge3IgaW5jbHVkZT1GQUxTRX0NCmxpYnJhcnkoZHBseXIpDQpsaWJyYXJ5KHBsb3RseSkNCmxpYnJhcnkoY2FyKQ0KbGlicmFyeShnZ3Bsb3QyKQ0KbGlicmFyeShvcGVueGxzeCkNCmxpYnJhcnkoY293cGxvdCkNCmxpYnJhcnkobWdjdikgDQpsaWJyYXJ5KGtuaXRyKQ0KbGlicmFyeShyZWFkeGwpDQpsaWJyYXJ5KGxtdGVzdCkNCmxpYnJhcnkobGF0dGljZSkNCnNldHdkKCJDOi9Vc2Vycy9UZW1wL0RvY3VtZW50cy9UcmFiYWpvL0JJQ29uc3VsdGFudHMvTW9kZWxvRG9sYXJCbHVlIikNCmBgYA0KDQojIEludHJvZHVjY2lvbg0KDQpFbiBBcmdlbnRpbmEsIGVsICJkw7NsYXIgYmx1ZSIgaGFjZSByZWZlcmVuY2lhIGEgbGEgY290aXphY2nDs24gbm8gb2ZpY2lhbCBkZWwgZMOzbGFyIGVzdGFkb3VuaWRlbnNlIGVuIGVsIG1lcmNhZG8gcGFyYWxlbG8uIEEgZGlmZXJlbmNpYSBkZWwgdGlwbyBkZSBjYW1iaW8gb2ZpY2lhbCBlc3RhYmxlY2lkbyBwb3IgZWwgQmFuY28gQ2VudHJhbCBkZSBsYSBSZXDDumJsaWNhIEFyZ2VudGluYSAoQkNSQSksIGVsIGTDs2xhciBibHVlIGVzIHVuIHZhbG9yIGRldGVybWluYWRvIHBvciBsYSBvZmVydGEgeSBsYSBkZW1hbmRhIGVuIHVuIG1lcmNhZG8gbm8gcmVndWxhZG8uIEVzdGEgY290aXphY2nDs24gc3VlbGUgc2VyIHV0aWxpemFkYSBjb21vIHVuIGluZGljYWRvciBkZSBsYSBwZXJjZXBjacOzbiBkZWwgbWVyY2FkbyBzb2JyZSBsYSBlc3RhYmlsaWRhZCBlY29uw7NtaWNhIHkgZmluYW5jaWVyYSBkZWwgcGHDrXMuIExhcyB2YXJpYWNpb25lcyBlbiBlbCB2YWxvciBkZWwgZMOzbGFyIGJsdWUgcHVlZGVuIHRlbmVyIHVuIGltcGFjdG8gc2lnbmlmaWNhdGl2byBlbiBsYSBlY29ub23DrWEgYXJnZW50aW5hLCB5YSBxdWUgaW5mbHV5ZW4gZW4gbGEgaW5mbGFjacOzbiwgbG9zIHByZWNpb3MsIGxhIGludmVyc2nDs24geSBsYSBmb3JtYSBkZSBhaG9ycm8gZGUgbGFzIHBlcnNvbmFzLg0KDQojIE9iamV0aXZvDQoNCkVsIHByb3DDs3NpdG8gY2VudHJhbCBkZSBlc3RlIHByb2dyYW1hIGVzIGNyZWFyIHVuIG1vZGVsbyBwYXJhIHByZWRlY2lyIGVsIGNvbXBvcnRhbWllbnRvIGRlbCBkw7NsYXIgYmx1ZSBlbiBBcmdlbnRpbmEuIFBhcmEgYWxjYW56YXIgZXN0ZSBvYmpldGl2bywgc2UgdXRpbGl6YXLDoW4gbGFzIHZhcmlhYmxlcyBkZWwgUkVNIChSZWxldmFtaWVudG8gZGUgRXhwZWN0YXRpdmFzIGRlIE1lcmNhZG8pIHkgYXNpIHBvZHJlbW9zIHVzYXIgZGljaGFzIHByZWRpY2Npb25lcyBwYXJhIHByb25vc3RpY2FyIGVsIHZhbG9yIGRlbCBkb2xhciBhIHNlaXMgbWVzZXMgZnV0dXJvcy4gRXN0ZSByZWxldmFtaWVudG8ganVudGEgcHJveWVjY2lvbmVzIHJlYWxpemFkYXMgZGUgZGl2ZXJzb3MgYW5hbGlzdGFzIGVjb27Ds21pY29zIHkgZmluYW5jaWVyb3MgZGVsIHBhw61zLg0KDQojIyBQcmVkaWNjaW9uZXMgZGVsIFJFTToNCg0KRWwgUmVsZXZhbWllbnRvIGRlIEV4cGVjdGF0aXZhcyBkZSBNZXJjYWRvIChSRU0pIGNvbnN0aXR1eWUgdW5hIGhlcnJhbWllbnRhIGZ1bmRhbWVudGFsIGRlbCBCYW5jbyBDZW50cmFsIGRlIGxhIFJlcMO6YmxpY2EgQXJnZW50aW5hLiBTdSBmaW5hbGlkYWQgZXMgcmVjb3BpbGFyIGxhcyBwcm95ZWNjaW9uZXMgZGUgZXNwZWNpYWxpc3RhcyBkZWwgbWVyY2FkbyBlbiByZWxhY2nDs24gY29uIHZhcmlhZGFzIHZhcmlhYmxlcyBlY29uw7NtaWNhcyBjbGF2ZS4gRXN0YXMgdmFyaWFibGVzIHNvbjoNCg0KMS4gQ3JlY2ltaWVudG8gZGVsIFByb2R1Y3RvIEludGVybm8gQnJ1dG8gKFBJQik6IFJlcHJlc2VudGEgbGEgZXhwYW5zacOzbiBlY29uw7NtaWNhIGRlbCBwYcOtcyBlbiB1biBwZXLDrW9kbyBlc3BlY8OtZmljby4NCjIuIEluZmxhY2nDs24gbyBJbmRpY2UgZGUgUHJlY2lvcyBhbCBDb25zdW1pZG9yIChJUEMpOiBSZWZsZWphIGVsIGF1bWVudG8gZ2VuZXJhbGl6YWRvIHkgc29zdGVuaWRvIGRlIGxvcyBwcmVjaW9zIGVuIGxhIGVjb25vbcOtYS4NCjMuIFRhc2EgZGUgSW50ZXLDqXMgKEJBRExBUik6IEluZGljYSBlbCBjb3N0byBkZWwgZGluZXJvIHkgcHVlZGUgaW5mbHVpciBlbiBsYSBpbnZlcnNpw7NuIHkgZWwgYWhvcnJvLg0KNC4gVGlwbyBkZSBDYW1iaW86IEVzIGVsIHZhbG9yIGRlIGxhIG1vbmVkYSBuYWNpb25hbCBlbiByZWxhY2nDs24gY29uIG90cmFzIG1vbmVkYXMsIGNvbW8gZWwgZMOzbGFyIGVzdGFkb3VuaWRlbnNlLg0KNS4gQmFsYW56YSBDb21lcmNpYWw6IE11ZXN0cmEgbGEgZGlmZXJlbmNpYSBlbnRyZSBsYXMgZXhwb3J0YWNpb25lcyBlIGltcG9ydGFjaW9uZXMgZGUgYmllbmVzLg0KNi4gRGVzb2N1cGFjaW9uIHBvcmNlbnR1YWw6IE11ZXN0cmEgZWwgcG9yY2VudGFqZSBkZSBsYSBwb2JsYWNpb24gZWNvbm9taWNhbWVudGUgYWN0aXZhIHF1ZSBzZSBlbmN1YW50cmEgZGVzZW1wbGVhZGEuDQoNCiMgKkRpc2NsYWltZXIqDQoNCipFcyBmdW5kYW1lbnRhbCByZW1hcmNhciBxdWUgZWwgbWVyY2FkbyBkZWwgZMOzbGFyIGJsdWUgZW4gQXJnZW50aW5hIGVzIGFsdGFtZW50ZSB2b2zDoXRpbCB5IGVzdMOhIHN1amV0byBhIGluZmx1ZW5jaWFzIGNvbXBsZWphcyB5IHZhcmlhYmxlcyBzb2NpYWxlcyBpbXBvc2libGVzIGRlIHByZWRlY2lyLiBQb3IgbG8gdGFudG8sIGN1YWxxdWllciBwcm9uw7NzdGljbyBnZW5lcmFkbyBhIHRyYXbDqXMgZGUgZXN0ZSBwcm9ncmFtYSBkZWJlIHNlciBjb25zaWRlcmFkbyBjb21vIHVuYSBBUFJPWElNQUNJw5NOIHkgdW5hIGhlcnJhbWllbnRhIG9yaWVudGF0aXZhLCBOTyBjb21vIHVuYSBwcmVkaWNjacOzbiBpbmZhbGlibGUuIExvcyByZXN1bHRhZG9zIG9idGVuaWRvcyBkZWJlbiBzZXIgaW50ZXJwcmV0YWRvcyBjb24gcHJlY2F1Y2nDs24geSBubyBkZWJlbiBjb25zdGl0dWlyIGxhIMO6bmljYSBiYXNlIHBhcmEgbGEgdG9tYSBkZSBkZWNpc2lvbmVzIGZpbmFuY2llcmFzIGltcG9ydGFudGVzLiBBZGVtYXMgcG9yIGxhIG5hdHVyYWxlemEgZGUgbG9zIGRhdG9zIHNlcmlhIG9wb3J0dW5vIHJlYWxpemFyIHVuIGFuYWxpc2kgZGUgc2VyaWVzIGRlIHRpZW1wbyBvIGRhdG9zIGxvbmdpdHVkaW5hbGVzLCBwZXJvIGVzZSBubyBlcyBlbCBvYmpldGl2byBkZSBlc3RlIGluZm9ybWUuKg0KDQoNCiMgRGF0YQ0KDQpMb3MgZGF0b3MgZnVlcm9uIHRvbWFkb3MgZGUgZnVlbnRlcyBjb25maWFibGVzIGNvbW8gQW1iaXRvIEZpbmFuY2llcm8gbyBzZXJpZXMgaGlzdG9yaWNhcyBwdWJsaWNhZGFzIHBvciBlbCBJTkRFQyBvIGxhIHNlY3JldGFyaWEgZGUgZGF0b3MgZGVsIGdvYmllcm5vLg0KDQpgYGB7ciBpbmNsdWRlPUZBTFNFfQ0KQmFzZV8yMDE2YTIzIDwtIHJlYWRfZXhjZWwoIkJhc2VfMjAxNmEyMy54bHN4IiwgDQogICAgc2hlZXQgPSAiZGF0b3NfaW50ZXJwb2xhZG9zIiwgY29sX3R5cGVzID0gYygiZGF0ZSIsIA0KICAgICAgICAibnVtZXJpYyIsICJudW1lcmljIiwgIm51bWVyaWMiLCANCiAgICAgICAgIm51bWVyaWMiLCAibnVtZXJpYyIsICJudW1lcmljIiwgDQogICAgICAgICJudW1lcmljIiwgIm51bWVyaWMiKSkNCkJhc2VfMjAxNmEyMyRmZWNoYT1hcy5EYXRlKEJhc2VfMjAxNmEyMyRmZWNoYSkNCkJhc2VfMjAxNmEyMw0KYGBgDQpDb21vIHNlIG11ZXN0cmEsIHRvbWFtb3Mgc29sbyBkYXRvcyBkZXNkZSBlbCBtZXMgZGUgZGljaWVtYnJlIGRlIDIwMTYsIGFsZ3VuYXMgc2VyaWVzIHNvbiBtZW5zdWFsZXMsIG90cmFzIHRyaW1lc3RyYWxlcyB5IG90cmFzIGRpYXJpYXMsIHBhcmEgZmFjaWxpdGFyIGVsIGFqdXN0ZSBkZWwgbW9kZWxvIGRlY2lkw60gbWVuc3VhbGl6YXIgbG9zIGRhdG9zIGNvbiB1bmEgaW50cmFwb2xhY2lvbiBzcGxpbmUgZW4gZWwgY2FzbyBkZSBsb3MgZGF0b3MgdHJpbWVzdHJhbGVzIChjb21vIGxvIHNvbiBQQkkgeSBkZXNvY3VwYWNpb24gcG9yY2VudHVhbCkgeSB0b21hciBsYSBwcmltZXIgb2JzZXJ2YWNpb24gZGUgY2FkYSBtZXMgZW4gZWwgY2FzbyBkZSBsYXMgc2VyaWVzIGRpYXJpYXMgKGNvbW8gbG8gc29uIHRhc2EgZGUgaW50ZXJlcyB5IHRpcG8gZGUgY2FtYmlvKQ0KDQojIE1vZGVsbyBMaW5lYWwNCg0KYGBge3IgaW5jbHVkZT1GQUxTRX0NCm1vZGVsPWxtKHZlbnRhIH4gZG9maWNpYWwgKyBleHBvcnRhY2lvbiArIHRhc2FfaW50ZXJlcytwaWJfbWVuc3VhbCArIGRlc29jdXBhY2lvbl9wb3JjICsgaXBjX25hY2lvbmFsICsgaW1wb3J0YWNpb24sIGRhdGEgPSBCYXNlXzIwMTZhMjMpDQpzdW1tYXJ5KG1vZGVsKQ0KYGBgDQpBanVzdGFtb3MgdW4gbW9kZWxvIGxpbmVhbCB5IHZlbW9zIGVuIGxhIHRhYmxhIEFOT1ZBIHF1ZSBzb2xhbWVudGUgZWwgZG9sYXIgb2ZpY2lhbCwgbGEgdGFzYSBkZSBpbnRlcmVzIHkgbGFzIGltcG9ydGFjaW9uZXMgc29uIHNpZ25pZmljYXRpdmFzLCBqdW50byBhbCBQQkkgc2kgdXNhbW9zIHVuIG5pdmVsIGRlIHNpZ25pZmljYWNpb24gZGVsIDEwJS4NClBhcmEgYXBsaWNhciBlc3RlIG1vZGVsbyBlc3RveSBzdXBvbmllbmRvIHF1ZSBsb3MgZGF0b3Mgc29uIGluZGVwZW5kaWVudGVzIGlndWFsbWVudGUgZGlzdHJpYnVpZG9zIHkgcXVlIGxvcyByZXNpZHVvcyBzZSBkaXN0cmlidXllbiBkZSBmb3JtYSBub3JtYWwgY29uIHZhcmlhbmNpYSBjb25zdGFudGUgKHN1cHVlc3RvcyBxdWUgc2FiZW1vcyBxdWUgbm8gc29uIHJlYWxlcykuIENvbnRpbnVvIGVsIGFuYWxpc2lzIGNvbiBsYSBjb21wcm9iYWNpb24gZGUgZGljaG9zIHN1cHVlc3Rvcy4NCg0KIyMgUmVzaWR1b3MNCg0KYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSxvdXQud2lkdGg9IjEwMCUifQ0KIyBDYWxjdWxhciBsb3MgcmVzaWR1b3MgZXN0YW5kYXJpemFkb3MNCnJlc2lkdW9zIDwtIHJlc2lkdWFscyhtb2RlbCkNCmZpdHRlZF92YWx1ZXMgPC0gbW9kZWwkZml0dGVkLnZhbHVlcw0KDQojIENyZWFyIHVuIGRhdGEgZnJhbWUgY29uIGxvcyByZXNpZHVvcyBlc3RhbmRhcml6YWRvcyB5IGxvcyB2YWxvcmVzIGFqdXN0YWRvcw0KcmVzaWR1YWxzX2RmIDwtIGRhdGEuZnJhbWUoRml0dGVkX1ZhbHVlcyA9IGZpdHRlZF92YWx1ZXMsIFJlc2lkdWFsZXMgPSByZXNpZHVvcykNCg0KIyBHcmFmaWNhciBsb3MgcmVzaWR1b3MgZXN0YW5kYXJpemFkb3MgdmVyc3VzIGxvcyB2YWxvcmVzIGFqdXN0YWRvcw0KZzE9Z2dwbG90KHJlc2lkdWFsc19kZiwgYWVzKHggPSBGaXR0ZWRfVmFsdWVzLCB5ID0gUmVzaWR1YWxlcykpICsNCiAgZ2VvbV9wb2ludChzaGFwZSA9IDIwKSArDQogIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDAsIGNvbG9yID0gInJlZCIpICsNCiAgeGxhYigiVmFsb3JlcyBBanVzdGFkb3MiKSArDQogIHlsYWIoIlJlc2lkdW9zIEVzdGFuZGFyaXphZG9zIikgKw0KICBnZ3RpdGxlKCJHcsOhZmljbyBkZSBSZXNpZHVvcyBFc3RhbmRhcml6YWRvcyB2cy4gVmFsb3JlcyBBanVzdGFkb3MiKQ0KIyBHcsOhZmljbyBRUSBkZSBsb3MgcmVzaWR1b3MgZXN0YW5kYXJpemFkb3MNCmcyPWdncGxvdChkYXRhLmZyYW1lKFJlc2lkdWFsZXMgPSByZXNpZHVvcyksIGFlcyhzYW1wbGUgPSBSZXNpZHVhbGVzKSkgKw0KICBnZW9tX3FxKCkgKw0KICBnZW9tX3FxX2xpbmUoKSArDQogIHhsYWIoIkN1YW50aWxlcyBUZcOzcmljb3MiKSArDQogIHlsYWIoIkN1YW50aWxlcyBkZSBsb3MgUmVzaWR1b3MgRXN0YW5kYXJpemFkb3MiKSArDQogIGdndGl0bGUoIkdyw6FmaWNvIFFRIGRlIGxvcyBSZXNpZHVvcyBFc3RhbmRhcml6YWRvcyIpDQpwbG90X2dyaWQoZzEsZzIpDQpgYGANClJlYWxpemFtb3MgbG9zIGdyYWZpY29zIGRlIHJlc2lkdW9zIGVzdGFuZGFyaXphZG8gdnMgdmFsb3JlcyBhanVzdGFkb3MgeSB2ZW1vcyBxdWUgYSBtZWRpZGEgcXVlIGF1bWVudGEgZWwgdmFsb3IgYWp1c3RhZG8gdGFtYmllbiBhdW1lbnRhIGxhIHZhcmlhbmNpYSBkZSBsb3MgcmVzaWR1b3MgeSBxdWUgbG9zIGN1YW50aWxlcyBvYnNlcnZhZG9zIHBvZHJpYW4gYXNpbWVqYXJzZSBhIHVuYSBkaXN0cmlidWNpb24gbm9ybWFsLCBkZSBpZ3VhbCBmb3JtYSBub3MgdmFsZHJlbW9zIGRlIHRlc3RzIGVzdGFkaXN0aWNvcyBwYXJhIHRlcm1pbmFyIGRlIGNvbmNsdWlyLg0KDQoNCmBgYHtyfQ0Kc2hhcGlyby50ZXN0KHJlc2lkdW9zKQ0KYGBgDQpFbCBTaGFwaXJvIFRlc3QgcGxhbnRlYToNCiQgSF8wKSAkIExvcyBkYXRvcyBwcm92aWVuZW4gZGUgdW5hIHBvYmxhY2nDs24gcXVlIHNpZ3VlIHVuYSBkaXN0cmlidWNpw7NuIG5vcm1hbC4gDQokIEhfMSkgJCBMb3MgZGF0b3Mgbm8gcHJvdmllbmVuIGRlIHVuYSBwb2JsYWNpw7NuIHF1ZSBzaWd1ZSB1bmEgZGlzdHJpYnVjacOzbiBub3JtYWwuDQpZIGNvbW8gZWwgdmFsb3IgZGUgcHJvYmFiaWxpZGFkIGFzb2NpYWRvIGVzIG1heW9yIGEgMC4wNSBwb2RlbW9zIGFzdW1pciBxdWUgc2UgY3VtcGxlIGxhIGhpcG90ZXNpcyBudWxhLg0KDQoNCmBgYHtyfQ0KYnB0ZXN0KG1vZGVsKSANCmBgYA0KDQpFbCB0ZXN0IGRlIEJyZXVzY2gtUGFnYW4gcGxhbnRlYToNCiQgSF8wKSAkIExhIHZhcmlhbnphIGRlIGxvcyByZXNpZHVvcyBlcyBjb25zdGFudGUgKGhvbW9jZWRhc3RpY2lkYWQpLiANCiQgSF8xKSAkIExhIHZhcmlhbnphIGRlIGxvcyByZXNpZHVvcyBubyBlcyBjb25zdGFudGUgKGhldGVyb2NlZGFzdGljaWRhZCkuDQpZIGNvbW8gZWwgdmFsb3IgZGUgcHJvYmFiaWxpZGFkIGFzb2NpYWRvIGVzIG1lbm9yICBhIDAuMDUgcG9kZW1vcyBhc3VtaXIgcXVlIHNlIGN1bXBsZSBsYSBoaXBvdGVzaXMgbnVsYS4NCg0KKk51ZXZhbWVudGUgdmFsZSBhY2xhcmFyIHF1ZSBlc3RvcyB0ZXN0IHVzYW4gc3VwdWVzdG9zIGRlIG5vcm1hbGlkYWQsIGxvcyBjdWFsZXMgc2FiZW1vcyBxdWUgbm8gc29uIHJlYWxlcywgcG9yIGxvIHF1ZSBkZWJlcmlhbW9zIHVzYXIgYWxndW4gdGlwbyBkZSB0ZXN0IG5vIHBhcmFtZXRyaWNvLCBwZXJvIGEgZmluZXMgcHLDoWN0aWNvcyBhbCB1c3VhcmlvIG5vIGxlIGludGVyZXNhIGVsIGN1bXBsaW1pZW50byBkZSBlc3RvcyBzdXB1ZXN0b3Mgc2lubyBxdWUgdGFuIGJpZW4gYWp1c3RhIGVsIG1vZGVsby4qDQoNCiMgVHJhbnNmb3JtYWNpb24NCg0KVmlzdG8geSBjb25zaWRlcmFuZG8gZWwgaW5jdW1wbGltaWVudG8gZGUgbG9zIHN1cHVlc3RvIHkgcXVlLCBlbiBsb3MgdWx0aW1vcyBhw7FvcywgZWwgY3JlY2ltaWVudG8gdGFudG8gZGVsIGRvbGFyIGNvbW8gZGUgbGEgdGFzYSBkZSBpbnRlcmVzIG5vIGZ1ZSBsaW5lYWwgc2lubyBtYXMgYmllbiBjdWFkcmF0aWNvIG8gZXhwb25lbmNpYWwsIGRlY2lkaSBhcGxpY2FyIHRyYW5zZm9ybWFjaW9uZXMgYWwgbW9kZWxvIGxpbmVhbC4NCkx1ZWdvIGRlIG11Y2hhcyBwcnVlYmFzIHByYWN0aWNhcyBvYnNlcnZlIHF1ZSBsYXMgcHJlZGljY2lvbmVzIG1hcyBleGFjdGFzIHkgZXN0YWJsZXMgc2UgZGFiYW4gYXBsaWNhbmRvIHRyYW5zZm9ybWFjaW9uIGxvZ2FyaXRtaWNhIGEgdG9kYXMgbGFzIHZhcmlhYmxlcy4NCg0KYGBge3IgaW5jbHVkZT1GQUxTRX0NCkJhc2VfMjAxNmEyMyRsb2dfdmVudGE9bG9nKEJhc2VfMjAxNmEyMyR2ZW50YSkNCkJhc2VfMjAxNmEyMyRsb2dfZG9maWNpYWw9bG9nKEJhc2VfMjAxNmEyMyRkb2ZpY2lhbCkNCkJhc2VfMjAxNmEyMyRsb2dfZXhwb3J0PWxvZyhCYXNlXzIwMTZhMjMkZXhwb3J0YWNpb24pDQpCYXNlXzIwMTZhMjMkbG9nX3Rhc2E9bG9nKEJhc2VfMjAxNmEyMyR0YXNhX2ludGVyZXMpDQpCYXNlXzIwMTZhMjMkbG9nX3BpYj1sb2coQmFzZV8yMDE2YTIzJHBpYl9tZW5zdWFsKQ0KQmFzZV8yMDE2YTIzJGxvZ19kZXNvYz1sb2coQmFzZV8yMDE2YTIzJGRlc29jdXBhY2lvbl9wb3JjKQ0KQmFzZV8yMDE2YTIzJGxvZ19pcGM9bG9nKEJhc2VfMjAxNmEyMyRpcGNfbmFjaW9uYWwpDQpCYXNlXzIwMTZhMjMkbG9nX2ltcG9ydD1sb2coQmFzZV8yMDE2YTIzJGltcG9ydGFjaW9uKQ0KDQoNCm1vZGVsb2c9bG0obG9nX3ZlbnRhIH4gbG9nX2RvZmljaWFsICsgbG9nX2V4cG9ydCArIGxvZ190YXNhKyBsb2dfcGliICsgbG9nX2Rlc29jICsgbG9nX2lwYyArIGxvZ19pbXBvcnQsIGRhdGEgPSBCYXNlXzIwMTZhMjMpDQpzdW1tYXJ5KG1vZGVsb2cpDQpgYGANClBvZHJpYW1vcyByZXBldGlyIGxhIGludGVycHJldGFjacOzbiBhcnJpYmEgbWVuY2lvbmFkYSBjb24gbGEgZGlmZXJlbmNpYSBkZSBxdWUgYWhvcmEgZXhwb3J0YWNpw7NuIHkgZGVzb2N1cGFjacOzbiBtZW5zdWFsIHNvbiBsYXMgw7puaWNhcyBubyBzaWduaWZpY2F0aXZhcyAoZGUgaWd1YWwgZm9ybWEgbm8gbGFzIGVsaW1pbmFyZW1vcyBkZWwgbW9kZWxvKQ0KDQoNCiMjIFJlc2lkdW9zIExvZw0KDQpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFLCBvdXQud2lkdGg9IjEwMCUifQ0KIyBDYWxjdWxhciBsb3MgcmVzaWR1b3MgZXN0YW5kYXJpemFkb3MNCnJlc2lkdW9zX2xvZyA8LSByZXNpZHVhbHMobW9kZWxvZykNCmZpdHRlZF92YWx1ZXNfbG9nIDwtIG1vZGVsb2ckZml0dGVkLnZhbHVlcw0KDQojIENyZWFyIHVuIGRhdGEgZnJhbWUgY29uIGxvcyByZXNpZHVvcyBlc3RhbmRhcml6YWRvcyB5IGxvcyB2YWxvcmVzIGFqdXN0YWRvcw0KcmVzaWR1YWxzX2RmIDwtIGRhdGEuZnJhbWUoRml0dGVkX1ZhbHVlcyA9IGZpdHRlZF92YWx1ZXNfbG9nLCBSZXNpZHVhbGVzID0gcmVzaWR1b3NfbG9nKQ0KDQojIEdyYWZpY2FyIGxvcyByZXNpZHVvcyBlc3RhbmRhcml6YWRvcyB2ZXJzdXMgbG9zIHZhbG9yZXMgYWp1c3RhZG9zDQpnMT1nZ3Bsb3QocmVzaWR1YWxzX2RmLCBhZXMoeCA9IEZpdHRlZF9WYWx1ZXMsIHkgPSBSZXNpZHVhbGVzKSkgKw0KICBnZW9tX3BvaW50KHNoYXBlID0gMjApICsNCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gMCwgY29sb3IgPSAicmVkIikgKw0KICB4bGFiKCJWYWxvcmVzIEFqdXN0YWRvcyIpICsNCiAgeWxhYigiUmVzaWR1b3MgRXN0YW5kYXJpemFkb3MiKSArDQogIGdndGl0bGUoIkdyw6FmaWNvIGRlIFJlc2lkdW9zIEVzdGFuZGFyaXphZG9zIHZzLiBWYWxvcmVzIEFqdXN0YWRvcyIpDQojIEdyw6FmaWNvIFFRIGRlIGxvcyByZXNpZHVvcyBlc3RhbmRhcml6YWRvcw0KZzI9Z2dwbG90KGRhdGEuZnJhbWUoUmVzaWR1YWxlcyA9IHJlc2lkdW9zX2xvZyksIGFlcyhzYW1wbGUgPSBSZXNpZHVhbGVzKSkgKw0KICBnZW9tX3FxKCkgKw0KICBnZW9tX3FxX2xpbmUoKSArDQogIHhsYWIoIkN1YW50aWxlcyBUZcOzcmljb3MiKSArDQogIHlsYWIoIkN1YW50aWxlcyBkZSBsb3MgUmVzaWR1b3MgRXN0YW5kYXJpemFkb3MiKSArDQogIGdndGl0bGUoIkdyw6FmaWNvIFFRIGRlIGxvcyBSZXNpZHVvcyBFc3RhbmRhcml6YWRvcyIpDQpwbG90X2dyaWQoZzEsZzIpDQpgYGANCg0KYGBge3J9DQpicHRlc3QobW9kZWxvZykgDQpzaGFwaXJvLnRlc3QocmVzaWR1b3NfbG9nKQ0KYGBgDQpBIGRpZmVyZW5jaWEgZGVsIGFuw6FsaXNpcyBhbnRlcmlvciwgYXF1aSBzaSB2ZW1vcyB1biBjdW1wbGltaWVudG8gZGUgbG9zIHN1cHVlc3RvcyB0YW50byBncmFmaWNhbWVudGUgY29tbyBlbiBsb3MgdGVzdCBhcGxpY2Fkb3MuDQoNCg0KIyMgSW50ZXJwcmV0YWNpb24gDQoNCkVsIG1vZGVsbyBhbCBxdWUgbGUgaW50cm9kdWNpcmVtb3MgbGFzIHByZWRpY2Npb25lcyBkZWwgUkVNIHBhcmEgb2J0ZW5lciB2YWxvcmVzIGRlIGRvbGFyIGJsdWUgZnV0dXJvIHNlcsOhIGVudG9uY2VzOg0KDQokJCBsb2coRG9sYXJCbHVlKT0xNy41KzEuMTMqbG9nKERvbGFyIE9maWNpYWwpLTAuMzIqbG9nKFRhc2EgSW50ZXJlcykrMC4zKmxvZyhJUENfezEwMH0pLTEuNTUqbG9nKFBCSSkrMC4zMSpsb2coSW1wb3J0YWNpb24pICAkJA0KDQoxLiBsb2dfZG9maWNpYWwNCjIuIGxvZ190YXNhX2ludGVyZXMNCjMuIGxvZ19pcGNfbmFjaW9uYWwgKGJhc2UgMTAwIGVuIGRpY2llbWJyZSBkZSAyMDE2KQ0KNC4gbG9nX3BpYl9tZW5zdWFsIChlbiBtaWxsb25lcyBkZSBkb2xhcmVzKQ0KNS4gbG9nX2ltcG9ydGFjaW9uIChlbiBtaWxsb25lcyBkZSBkb2xhcmVzKQ0KNi4gbG9nX2Rlc29jdXBhY2lvbl9wb3JjIA0KNy4gbG9fZXhwb3J0YWNpb24gKGVuIG1pbGxvbmVzIGRlIGRvbGFyZXMpDQoNCg0KIyBBcGxpY2FjacOzbiBncsOhZmljYQ0KDQpQYXJhIHZpc3VhbGl6YXIgY29tbyBwcmVkaWNlIGVsIG1vZGVsbyBxdWUgYWp1c3RhbW9zIHRvbWFyZW1vcyBsYXMgcHJlZGljY2lvbmVzIGRlIGxvcyBkYXRvcyBxdWUgeWEgdGVuZW1vcyB5IGxhcyBjb21wYXJhcmVtb3MgY29uIGxvcyB2YWxvcmVzIHJlYWxlcyBxdWUgdHV2byBlbCBkb2xhciBibHVlLiBBZGVtYXMgbGUgYWdlZ2Ftb3MgZG9zIGJhbmRhcyBhbCBncmFmaWNvLCB1bmEgcXVlIGluZGljYSBlbCAxNzAlIHkgb3RyYSBxdWUgaW5kaWNhIGVsIDIxMCUgZGVsIHZhbG9yIGRlbCBkb2xhciBvZmljaWFsIHF1ZSBwb3IgZXZpZGVuY2lhIG9ic2VydmFjaW9uYWwgc29uIGxhcyBmcmFuamFzIGVudHJlIGxhcyBxdWUgZXN0dXZvIGZsdWN0dWFuZG8gZWwgZG9sYXIgYmx1ZSBlbiBsb3MgdWx0aW1vcyBhw7Fvcy4NCg0KYGBge3J9DQpCYXNlXzIwMTZhMjMkeXByZWRsb2c9ZXhwKHByZWRpY3QobW9kZWxvZyxuZXdkYXRhID0gQmFzZV8yMDE2YTIzKSkNCkJhc2VfMjAxNmEyMyRkb2ZpY2lhbDE3PUJhc2VfMjAxNmEyMyRkb2ZpY2lhbCoxLjcNCkJhc2VfMjAxNmEyMyRkb2ZpY2lhbDIxPUJhc2VfMjAxNmEyMyRkb2ZpY2lhbCoyLjENCmBgYA0KDQoNCmBgYHtyLG91dC53aWR0aD0iMTAwJSJ9DQpncmFmaWNvX3Bsb3RseSA8LSBwbG90X2x5KGRhdGEgPSBCYXNlXzIwMTZhMjMsIHggPSB+ZmVjaGEpICU+JQ0KICBhZGRfbGluZXMoeSA9IH52ZW50YSwgbmFtZSA9ICJWZW50YSIsIGxpbmUgPSBsaXN0KGNvbG9yID0gImJsdWUiKSkgJT4lDQogIGFkZF9saW5lcyh5ID0gfnlwcmVkbG9nLCBuYW1lID0gIlByZWRpY2Npb25lcyIsIGxpbmUgPSBsaXN0KGNvbG9yID0gInJlZCIpKSAlPiUNCiAgYWRkX2xpbmVzKHkgPSB+ZG9maWNpYWwxNywgbmFtZSA9ICIxNzAlIERvbGFyIE9maWNpYWwiLCBsaW5lID0gbGlzdChjb2xvciA9ICJncmF5IiwgZGFzaCA9ICJkYXNoIikpICU+JQ0KICBhZGRfbGluZXMoeSA9IH5kb2ZpY2lhbDIxLCBuYW1lID0gIjIxMCUgRG9sYXIgT2ZpY2lhbCIsIGxpbmUgPSBsaXN0KGNvbG9yID0gImdyYXkiLCBkYXNoID0gImRhc2giKSkgJT4lDQogIGxheW91dCh0aXRsZSA9ICJDb21wYXJhY2nDs24gUHJlZGljY2lvbmVzIHZzIEJsdWUgcmVhbCIsDQogICAgICAgICB4YXhpcyA9IGxpc3QodGl0bGUgPSAiRmVjaGEiKSwNCiAgICAgICAgIHlheGlzID0gbGlzdCh0aXRsZSA9ICJWYWxvcmVzIikpDQoNCmdyYWZpY29fcGxvdGx5DQpgYGANCg0KIyBDb25jbHVzaW9uIA0KDQpBcGxpY2FuZG8gbGFzIHByZWRpY2Npb25lcyBxdWUgc2UgcHVibGljYW4gZW4gZWwgUkVNIHkgdXRpbGl6YW5kbyBlc3RlIG1vZGVsbyBwb2RlbW8gdGVuZXIgdW5hIG5vY2lvbiBkZWwgY29tcG9ydGFtaWVudG8gZnV0dXJvIGRlbCBkb2xhciBibHVlLiBFbiBsYSBwcmFjdGljYSBwb2RlbW9zIGlyIGFjdHVhbGl6YW5kbyBsb3MgZGF0b3MgcXVlIGFqdXN0YW4gbGEgbW9kZWxvIHkgb2JzZXJ2YW5kbyBsb3MgcmVzdWx0YWRvcy4gRW4gbWkgZXhwZXJpZW5jaWEsIHNpIGJpZW4gZWwgbW9kZWxvIHNvYnJlIGVzdGltYSwgcmVzdWx0YSB1dGlsIHBhcmEgaWRlbnRpZmljYXIgdW4gc2FsdG8gY2VyY2FubyBjb21vIHNlIGRpbyBwb3IgZWplbXBsbyBsdWVnbyBkZSBsYXMgZWxlY2Npb25lcyBQQVNPIDIwMjMNCg0KIyBBZGljaW9uYWw6IE90cm9zIE1vZGVsb3MgQWp1c3RhZG8NCg0KQ29tbyByZW1hcnF1ZSBkdXJhbnRlIHRvZG8gZWwgaW5mb3JtZSwgc2FiZW1vcyBxdWUgZWwgZG9sYXIgYmx1ZSBubyBzZSBjb21wb3J0YSBkZSBmb3JtYSBsaW5lYWwgeSBxdWUgZXN0b3MgbW9kZWxvcyBlc3RhbiBhanVzdGFkb3MgYSBiYXNlIGRlIHN1cHVlc3RvcyBlcnJvbmVvcy4gUG9yIGVzdG8gcG9kcmlhIGNvbnRpbnVhcnNlIGVsIGFuYWxpc2lzIGFqdXN0YW5kbyB1biBtb2RlbG8gYWRpdGl2byBubyBsaW5lYWwuDQoNCmBgYHtyfQ0KDQptb2RlbG9fYmx1ZV9hZGl0aXZvPWdhbSh2ZW50YSB+IHMoZG9maWNpYWwpICsgcyhleHBvcnRhY2lvbikgKyBzKGltcG9ydGFjaW9uKSArIHModGFzYV9pbnRlcmVzKSArIHMocGliX21lbnN1YWwpICsgcyhkZXNvY3VwYWNpb25fcG9yYykgKyBzKGlwY19uYWNpb25hbCksDQogICAgICAgICAgICAgICAgICAgICAgICBkYXRhID0gQmFzZV8yMDE2YTIzKQ0Kc3VtbWFyeShtb2RlbG9fYmx1ZV9hZGl0aXZvKQ0KYGBgDQpObyBwcm9mdW5kYXJpc2FyZSBlbiBlbCBhbmFsaXNpcyBkZSBlc3RlIG1vZGVsbyBwb3IgZmFsdGEgZGUgZXJyYW1pZW50YXMgdGVvcmljYXMsIHBlcm8gcG9kcmlhbW9zIG9ic2VydmFybG8geSBjb21wYXJhcmxvIGVuIGVsIGdyYWZpY28gYW50ZXJpb3INCg0KYGBge3Isb3V0LndpZHRoPSIxMDAlIn0NCkJhc2VfMjAxNmEyMyR5cHJlZGdhbT1wcmVkaWN0KG1vZGVsb19ibHVlX2FkaXRpdm8sbmV3ZGF0YSA9IEJhc2VfMjAxNmEyMykNCmdyYWZpY29fcGxvdGx5IDwtIHBsb3RfbHkoZGF0YSA9IEJhc2VfMjAxNmEyMywgeCA9IH5mZWNoYSkgJT4lDQogIGFkZF9saW5lcyh5ID0gfnZlbnRhLCBuYW1lID0gIlZlbnRhIiwgbGluZSA9IGxpc3QoY29sb3IgPSAiYmx1ZSIpKSAlPiUNCiAgYWRkX2xpbmVzKHkgPSB+eXByZWRsb2csIG5hbWUgPSAiTW9kZWxvIExvZyIsIGxpbmUgPSBsaXN0KGNvbG9yID0gInJlZCIpKSAlPiUNCiAgYWRkX2xpbmVzKHkgPSB+eXByZWRnYW0sIG5hbWUgPSAiTW9kZWxvIEdBTSIsIGxpbmUgPSBsaXN0KGNvbG9yID0gImdyZWVuIikpICU+JQ0KICBhZGRfbGluZXMoeSA9IH5kb2ZpY2lhbDE3LCBuYW1lID0gIjE3MCUgRG9sYXIgT2ZpY2lhbCIsIGxpbmUgPSBsaXN0KGNvbG9yID0gImdyYXkiLCBkYXNoID0gImRhc2giKSkgJT4lDQogIGFkZF9saW5lcyh5ID0gfmRvZmljaWFsMjEsIG5hbWUgPSAiMjEwJSBEb2xhciBPZmljaWFsIiwgbGluZSA9IGxpc3QoY29sb3IgPSAiZ3JheSIsIGRhc2ggPSAiZGFzaCIpKSAlPiUNCiAgbGF5b3V0KHRpdGxlID0gIkNvbXBhcmFjacOzbiBQcmVkaWNjaW9uZXMgdnMgQmx1ZSByZWFsIiwNCiAgICAgICAgIHhheGlzID0gbGlzdCh0aXRsZSA9ICJGZWNoYSIpLA0KICAgICAgICAgeWF4aXMgPSBsaXN0KHRpdGxlID0gIlZhbG9yZXMiKSkNCg0KZ3JhZmljb19wbG90bHkNCmBgYA0KDQpMYXMgcHJlZGljY2lvbmVzIGRlIGVzdGUgbW9kZWxvIHByYWN0aW1hZW50ZSBzZSBzdXBlcnBvbmVuIGNvbiBlbCB2YWxvciByZWFsIHF1ZSBmdWUgdG9tYW5kbyBlbCBkb2xhciBibHVlLCBsbyBxdWUgaW5kaWNhIHVuIGdyYW4gYWp1c3RlLCBwZXJvIGVuIGxhIHByYWN0aWNhIHVuIHBlcXVlw7FvIGNhbWJpbyBlbiBsYXMgZXhwb3J0YWNpb25lcyBhdW1lbnRhYmEgbXVjaG8gZWwgZXJyb3IsIGxvIHF1ZSBub3MgbGxldmEgYSB1c2FybG8gc29sbyBjb21vIHVuIGNvbXBsZW1lbnRvIGRlbCBtb2RlbG8gYW50ZXJpb3IuDQo=